# amplitude.dict -- definition of a Dict class that allows dot-notation attribute access

class Dict(dict):
    """A Dict class that
        * allows dot-notation attribute access, returning None if key not found
        * sorts keys on calls to keys() and items() and repr(), making many things easier
    """

    def __init__(dnQquTPXVfOB58Y0, **kwargs):
        # the crazy name for self is necessary to avoid key conflicts with "self" (used as a key, e.g., in WordPress API)
        def dict_list_val(inlist):
            l = []
            for i in inlist:
                if type(i)==dict:
                    l.append(Dict(**i))
                elif type(i)==list:
                    l.append(make_list(i))
                else:
                    l.append(i)
            return l
        for k in kwargs.keys():
            if type(kwargs[k])==dict:
                dnQquTPXVfOB58Y0[k] = Dict(**kwargs[k])
            elif type(kwargs[k])==list:
                dnQquTPXVfOB58Y0[k] = dict_list_val(kwargs[k])
            else:
                dnQquTPXVfOB58Y0[k] = kwargs[k]
    
    # allow dot-notation attribute access alongside dict-notation
    def __getattr__(self, name):
        return dict.get(self, name)       # returns None if the key is not found.

    def __setattr__(self, name, val):
        self[name] = val

    def __repr__(self):
        """displays the Dict with keys in alphabetical order, for consistent test output."""
        keys = self.keys()
        keys.sort()
        return "{" + ", ".join([u"%s: %s" % (repr(k), repr(self[k])) for k in keys]) + "}"

    def keys(self, cmp=None, key=None, reverse=False):
        """sort the keys before returning them"""
        ks = dict.keys(self)
        ks.sort(cmp=cmp, key=key, reverse=reverse)
        return ks
        
    def values(self, cmp=None, key=None, reverse=False):
        """sort the values in the same order as the keys"""
        ks = self.keys(cmp=cmp, key=key, reverse=reverse)
        return [self[k] for k in ks]
    
    # convenience methods

    def set(self, prefix_=None, **args):
        "eventual replacement for Dict.set_attribs()"
        return self.set_attribs(prefix=prefix_, **args)
    
    def set_attribs(self, prefix=None, **args):
        """set the instance attribs to the values in args
            If prefix is not None, only set the args that have the optional prefix
            (very useful for getting stuff out of forms painlessly) -- 
            the prefix is stripped from the attribute name.
        Usage:
        >>> d = Dict()
        >>> attribs = {'session_key': 'gobbledygook', 'user_email': 'nobody@home.com', 'user_password': 'secretpwd'}
        >>> d.set_attribs('user_', **attribs)
        >>> 'email' in d.keys(), 'password' in d.keys(), 'session_key' in d.keys()
        (True, True, False)
        """
        for k in args.keys():
            # only set self[k] if the prefix is None or k begins with the prefix
            if prefix is None or prefix == k[0:len(prefix)]:
                if prefix is None:
                    newkey = k                # use the whole key
                else: 
                    newkey = k[len(prefix):]  # use the part of the key following the prefix
                self[newkey] = args[k]

    def from_prefix(self, prefix):
        """return a Dict containing the keys from self that have the given prefix, with the prefix removed"""
        d = Dict()
        for k in [k for k in self.keys() if k[:len(prefix)]==prefix]:
            d[k[len(prefix):]] = self[k]
        return d


class StringDict(Dict):
    # casts all return values to strings, returns empty string if not found. Useful for web contexts 
    def __getattr__(self, name):
        return unicode(dict.get(self, name) or u'')